// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rbchat.logic.chat_root.model;

import android.content.Context;

import com.eva.epc.common.util.CommonUtils;
import com.google.gson.Gson;
import com.x52im.rainbowchat.http.logic.dto.TimeToolKit;
import com.x52im.rbchat.MyApplication;
import com.x52im.rbchat.R;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rainbowchat.im.dto.MsgBody4Friend;
import com.x52im.rainbowchat.im.dto.MsgType;
import com.x52im.rainbowchat.im.dto.RevokedMeta;
import com.x52im.rbchat.logic.chat_root.sendfile.ReceivedFileHelper;
import com.x52im.rbchat.logic.chat_root.sendshortvideo.ReceivedShortVideoHelper;
import com.x52im.rbchat.utils.ToolKits;

import net.x52im.mobileimsdk.android.ClientCoreSDK;

import java.text.MessageFormat;

/**
 * 本类仅作为 Message 的辅助类使用。
 *
 * 作用是将一些可以剥离出来的实用性代码放到本类中，从而降低Message的代码行数，提升
 * Message类的可维护性和代码可读性，别无它用！本类中的代码，可以无条件合并到
 * Message中（如果你不介意代码量大，看起来很吓的人话。。。）。
 *
 * @author Jack Jiang
 * @since 6.0
 * @see Message
 */
public class MessageExt
{
    //------------------------------------------------------------------------------------------- 生成Message的实用方法 START
    public static Message createChatMsgEntity_OUTGO_TEXT(String message, String fingerPrint)
    {
        Message cm = new Message(ClientCoreSDK.getInstance().getCurrentLoginUserId()
                , "我", ToolKits.getTimeStamp(), message, MsgType.TYPE_TEXT);
        cm.setFingerPrintOfProtocal(fingerPrint);
        return cm;
    }
    public static Message createChatMsgEntity_OUTGO_IMAGE(String fileName, String fingerPrint)
    {
        // 当是图片消息时，message里存放的就是图片所存放于服务端的文件名（原图而非缩略图的文件名哦）
        Message cm = new Message(ClientCoreSDK.getInstance().getCurrentLoginUserId()
                , "我", ToolKits.getTimeStamp(), fileName, MsgType.TYPE_IMAGE, Message.SendStatusSecondary.pending);
        cm.setFingerPrintOfProtocal(fingerPrint);
        return cm;
    }
    public static Message createChatMsgEntity_OUTGO_VOICE(String fileName, String fingerPrint)
    {
        // 当是图片消息时，message里存放的就是图片所存放于服务端的文件名（原图而非缩略图的文件名哦）
        Message cm = new Message(ClientCoreSDK.getInstance().getCurrentLoginUserId()
                ,"我", ToolKits.getTimeStamp(), fileName, MsgType.TYPE_VOICE, Message.SendStatusSecondary.pending);
        cm.setFingerPrintOfProtocal(fingerPrint);
        return cm;
    }
    public static Message createChatMsgEntity_OUTGO_GIFT$FOR$SEND(String giftIdent, String fingerPrint)
    {
        Message cm = new Message(ClientCoreSDK.getInstance().getCurrentLoginUserId()
                , "我", ToolKits.getTimeStamp(), giftIdent, MsgType.TYPE_GIFT$SEND);
        cm.setFingerPrintOfProtocal(fingerPrint);
        return cm;

    }
    public static Message createChatMsgEntity_OUTGO_GIFT$FOR$GET(String giftIdent, String fingerPrint)
    {
        Message cm = new Message(ClientCoreSDK.getInstance().getCurrentLoginUserId()
                ,"我", ToolKits.getTimeStamp(), giftIdent, MsgType.TYPE_GIFT$GET);
        cm.setFingerPrintOfProtocal(fingerPrint);
        return cm;
    }
    public static Message createChatMsgEntity_OUTGO_FILE(FileMeta fm, String fingerPrint)
    {
        // 当是文件消息时，message里存放的就是FileMeta对象
        Message cm = new Message(ClientCoreSDK.getInstance().getCurrentLoginUserId()
                ,"我"
                , ToolKits.getTimeStamp()
                , new Gson().toJson(fm)
                , MsgType.TYPE_FILE
                , Message.SendStatusSecondary.pending);
        cm.setFingerPrintOfProtocal(fingerPrint);
        return cm;

    }
    public static Message createChatMsgEntity_OUTGO_SHORTVIDEO(FileMeta fileMeta, String fingerPrint)
    {
        // 当是短视频消息时，message里存放的就是FileMeta对象
        Message cm = new Message(ClientCoreSDK.getInstance().getCurrentLoginUserId()
                ,"我"
                , ToolKits.getTimeStamp()
                , new Gson().toJson(fileMeta)
                , MsgType.TYPE_SHORTVIDEO
                , Message.SendStatusSecondary.pending);
        cm.setFingerPrintOfProtocal(fingerPrint);
        return cm;

    }
    public static Message createChatMsgEntity_OUTGO_CONTACT(ContactMeta ccontactMeta, String fingerPrint)
    {
        // 当是个人名片消息时，message里存放的就是ContactMeta对象
        Message cm = new Message(ClientCoreSDK.getInstance().getCurrentLoginUserId()
                ,"我"
                , ToolKits.getTimeStamp()
                , new Gson().toJson(ccontactMeta)
                , MsgType.TYPE_CONTACT);
        cm.setFingerPrintOfProtocal(fingerPrint);
        return cm;

    }
    public static Message createChatMsgEntity_OUTGO_LOCATION(LocationMeta locationMeta, String fingerPrint)
    {
        // 当是位置消息时，message里存放的就是LocationMeta对象
        Message cm = new Message(ClientCoreSDK.getInstance().getCurrentLoginUserId()
                ,"我"
                , ToolKits.getTimeStamp()
                , new Gson().toJson(locationMeta)
                , MsgType.TYPE_LOCATION);
        cm.setFingerPrintOfProtocal(fingerPrint);
        return cm;

    }
    public static Message createChatMsgEntity_OUTGO_VOIPRECORD(VoipRecordMeta voipRecordMeta, String fingerPrint)
    {
        // 当是位置消息时，message里存放的就是LocationMeta对象
        Message cm = new Message(ClientCoreSDK.getInstance().getCurrentLoginInfo().getLoginUserId()
                ,"我"
                , ToolKits.getTimeStamp()
                , new Gson().toJson(voipRecordMeta)
                , MsgType.TYPE_VOIP$RECORD);
        cm.setFingerPrintOfProtocal(fingerPrint);
        return cm;

    }

    public static Message createChatMsgEntity_INCOME_TEXT(String senderId, String nickName, String message, long time)
    {
        return new Message(senderId, nickName, time <= 0 ?ToolKits.getTimeStamp():time, message, MsgType.TYPE_TEXT);
    }

    public static Message createChatMsgEntity_INCOME_IMAGE(String senderId, String nickName, String fileName, long time)
    {
        // 当是图片消息时，message里存放的就是图片所存放于服务端的文件名（原图而非缩略图的文件名哦）
        return new Message(senderId, nickName, time <= 0 ?ToolKits.getTimeStamp():time, fileName, MsgType.TYPE_IMAGE);
    }

    public static Message createChatMsgEntity_INCOME_VOICE(String senderId, String nickName, String fileName, long time)
    {
        // 当是图片消息时，message里存放的就是语音留言所存放于服务端的文件名
        return new Message(senderId, nickName, time <= 0 ?ToolKits.getTimeStamp():time, fileName, MsgType.TYPE_VOICE);
    }

    public static Message createChatMsgEntity_INCOME_GIFT$FOR$SEND(String senderId, String nickName, String giftIdent, long time)
    {
        return new Message(senderId, nickName, time <= 0 ?ToolKits.getTimeStamp():time, giftIdent, MsgType.TYPE_GIFT$SEND);
    }

    public static Message createChatMsgEntity_INCOME_GIFT$FOR$GET(String senderId, String nickName, String giftIdent, long time)
    {
        return new Message(senderId, nickName, time <= 0 ?ToolKits.getTimeStamp():time, giftIdent, MsgType.TYPE_GIFT$GET);
    }

    public static Message createChatMsgEntity_INCOME_FILE(String senderId, String nickName, FileMeta fileMeta, long time)
    {
        // 注意：因为是对方发过来的文件，所以此路径应是对方收到后的保存绝对路径（对方发送时此路径传的就是null
        // ），且应该由接方收到消息后来决定（因为手机型号不同可能文件目录的规则不相同，比如老的android跟
        // android 4.4以上就不同），所以此处来补上此绝对路径字段是合理的
        String filePath = ReceivedFileHelper.getReceivedFileSavedDirHasSlash() + fileMeta.getFileName();

        // 当是文件消息时，message里存放的就是ComeFileMeta对象
        return new Message(senderId, nickName
                , time <= 0 ?ToolKits.getTimeStamp():time//time == null ?ToolKits.getTime():time
                , new Gson().toJson(fileMeta.setFilePath(filePath))
                , MsgType.TYPE_FILE);
    }

    public static Message createChatMsgEntity_INCOME_SYSTEAMINFO(String senderId, String message, long time)
    {
        return new Message(senderId, "", time <= 0 ?ToolKits.getTimeStamp():time, message, MsgType.TYPE_SYSTEAM$INFO);
    }

    public static Message createChatMsgEntity_INCOME_REVOKE(String senderId, String message, long time)
    {
        return new Message(senderId, "", time <= 0 ?ToolKits.getTimeStamp():time, message, MsgType.TYPE_REVOKE);
    }

    public static Message createChatMsgEntity_INCOME_SHORTVIDEO(String senderId, String nickName, FileMeta fileMeta, long time)
    {
        // 注意：因为是对方发过来的视频，所以此路径应是对方收到后的保存绝对路径（对方发送时此路径传的就是null
        // ），且应该由接方收到消息后来决定（因为手机型号不同可能文件目录的规则不相同，比如老的android跟
        // android 4.4以上就不同），所以此处来补上此绝对路径字段是合理的
        String filePath = ReceivedShortVideoHelper.getReceivedShortVideoSavedDirHasSlash() + fileMeta.getFileName();

        // 当是短视频消息时，message里存放的就是FileMeta对象
        return new Message(senderId, nickName
                , time <= 0 ?ToolKits.getTimeStamp():time
                , new Gson().toJson(fileMeta.setFilePath(filePath))
                , MsgType.TYPE_SHORTVIDEO);
    }

    /**
     * @param nickName 消息发送者的昵称
     * @param contactMeta "名片"信息
     * @param time
     * @return
     */
    public static Message createChatMsgEntity_INCOME_CONTACT(String senderId, String nickName, ContactMeta contactMeta, long time)
    {
        // 当是个人名片消息时，message里存放的就是ContactMeta对象
        return new Message(senderId, nickName
                , time <= 0 ?ToolKits.getTimeStamp():time
                , new Gson().toJson(contactMeta)
                , MsgType.TYPE_CONTACT);
    }

    public static Message createChatMsgEntity_INCOME_LOCATION(String senderId, String nickName, LocationMeta lm, long time)
    {
        // 当是个人名片消息时，message里存放的就是ContactMeta对象
        return new Message(senderId, nickName
                , time <= 0 ?ToolKits.getTimeStamp():time
                , new Gson().toJson(lm)
                , MsgType.TYPE_LOCATION);
    }

    public static Message createChatMsgEntity_INCOME_VOIPRECORD(String senderId, String nickName, VoipRecordMeta vrm, long time)
    {
        // 当是实时音视频记录消息时，message里存放的就是VoipRecordMeta对象
        return new Message(senderId, nickName
                , time <= 0 ?ToolKits.getTimeStamp():time
                , new Gson().toJson(vrm)
                , MsgType.TYPE_VOIP$RECORD);
    }
    //------------------------------------------------------------------------------------------- 生成Message的实用方法 END


    //------------------------------------------------------------------------------------------- “收到”的消息的一些实用方法 START
    /**
     * 根据消息类型，显示友好的文字内容供某些情况下的预览（比如首页”消息“列表中、系统通知等）.
     *
     * @param messageContent 真正的聊天文本内容（该内容可能是扁平文本（文本聊天消息）、文件（语音留言、图片消息）），是TextMessage中的m内容
     * @return 返回消息文本（仅用于ui显示哦）
     * @since 2.2
     */
    public static String parseMessageContentPreview(Context context, String messageContent, int msgType)
    {
        if(messageContent == null)
            return "";

        // 自kchat2.2(20140212)后，此字段将用于消息内容的显示
        String messageContentForShow = "";

        switch (msgType)
        {
            case MsgBody4Friend.TYPE_IMAGE:
                messageContentForShow = "[" + context.getString(R.string.general_image_desc) + "]";
                break;
            case MsgBody4Friend.TYPE_VOICE:
                messageContentForShow = "[" + context.getString(R.string.general_voice_desc) + "]";
                break;
            case MsgBody4Friend.TYPE_GIFT$SEND:
                messageContentForShow = "[" + context.getString(R.string.general_gift_send_desc) + "]";
                break;
            case MsgBody4Friend.TYPE_GIFT$GET:
                messageContentForShow = "[" + context.getString(R.string.general_gift_get_desc) + "]";
                break;
            case MsgBody4Friend.TYPE_FILE:
                // 文件消息的内容体是FileMeta对象的JSON形式
                FileMeta fm = FileMeta.fromJSON(messageContent);
                messageContentForShow = "[" + context.getString(R.string.general_bigfile_desc) + "]" + (fm != null ? " " + fm.getFileName() : "");
                break;
            case MsgBody4Friend.TYPE_SHORTVIDEO:
                messageContentForShow = "[" + context.getString(R.string.general_shortvideo_desc) + "]";
                break;
            case MsgBody4Friend.TYPE_CONTACT: {
                // 名片消息的内容体是CardMeta对象的JSON形式
                ContactMeta cm = ContactMeta.fromJSON(messageContent);
                messageContentForShow = "[" + context.getString(cm.getType() == ContactMeta.TYPE_USER ?
                        R.string.general_card_user_desc: R.string.general_card_group_desc) + "]";
                break;
            }
            case MsgBody4Friend.TYPE_LOCATION:
                // 位置消息的内容体是LocationMeta对象的JSON形式
                LocationMeta lm = LocationMeta.fromJSON(messageContent);
                String extra = (lm == null?"":(CommonUtils.isStringEmpty(lm.getLocationTitle(), true)?"":lm.getLocationTitle()));
                messageContentForShow = "[" + context.getString(R.string.general_location_desc) + "]"+extra;
                break;
            case MsgBody4Friend.TYPE_REVOKE:
                // 位置消息的内容体是LocationMeta对象的JSON形式
                RevokedMeta rm = RevokedMeta.fromJSON(messageContent);
                messageContentForShow = getMessageContentPreviewForRevoked(context, rm);
                break;
            case MsgType.TYPE_VOIP$RECORD: {
                // 实时音视频聊天记录消息的内容体是VoipRecordMeta对象的JSON形式
                VoipRecordMeta vrm = VoipRecordMeta.fromJSON(messageContent);
                String prefix = "["+context.getResources().getString( vrm.getVoipType() == VoipRecordMeta.VOIP_TYPE_VOICE
                        ? R.string.general_voip_voice_desc : R.string.general_voip_video_desc)+"]";
                String content = null;
                switch (vrm.getRecordType()) {
                    case VoipRecordMeta.RECORD_TYPE_REQUEST_CANCEL:
                        content = context.getResources().getString(R.string.voip_record_cancel_common);
                        break;
                    case VoipRecordMeta.RECORD_TYPE_REQUEST_REJECT:
                        content = content = context.getResources().getString(R.string.voip_record_reject_common);
                        break;
                    case VoipRecordMeta.RECORD_TYPE_CALLING_TIMEOUT:
                        content = content = context.getResources().getString(R.string.voip_record_timeout2_common);
                        break;
                    case VoipRecordMeta.RECORD_TYPE_CHATTING_DURATION:
                        if(vrm.getDuration() > 0) {
                            content = MessageFormat.format(context.getResources().getString(R.string.voip_record_duration_common)
                                    , TimeToolKit.getMMSSFromSS(vrm.getDuration()));
                        }
                        break;
                }
                messageContentForShow = prefix + (content != null?content:"");
                break;
            }
            default:
                messageContentForShow = messageContent;
                break;
        }

        return messageContentForShow;
    }

    /**
     * 被撤回的消息，预览内容显示。
     *
     * @param context 上下文对象
     * @param rm 被撤回消息的内容体对象
     * @return 返回内容预览
     */
    public static String getMessageContentPreviewForRevoked(Context context, RevokedMeta rm)
    {
        if(context == null)
            return "";

        String ret = context.getString(R.string.chat_message_revoked_by_default);
        if(rm != null){
            String uidForOperator = rm.getUid();
            String nickeNameForOperator = rm.getNickName();

            // 被"撤回"者的uid（当前用于群聊时，由管理员撤回其它群员消息时存入被撤回消息的发送者uid，其它余情况下本参数为空！）
            String beUid = rm.getBeUid();
            // 被"撤回"者的昵称（当前用于群聊时，由管理员撤回其它群员消息时存入被撤回消息的发送者uid，其它余情况下本参数为空！）
            String beNickname = rm.getBeNickName();

            RosterElementEntity localRee = MyApplication.getInstance2().getIMClientManager().getLocalUserInfo();

            String revokedOperatorNick = "";
            String beRevokesOperatorNick = "";

            // 撤回者昵称显示内容
            if(localRee != null && uidForOperator != null && uidForOperator.equals(localRee.getUser_uid())){
                revokedOperatorNick = "你";
            }
            else{
                revokedOperatorNick = "\""+nickeNameForOperator+"\" ";
            }

            // 被撤回者昵称显示内容
            if(beUid != null){
                if(uidForOperator != null && !beUid.equals(uidForOperator)) {
                    if(localRee != null && beUid.equals(localRee.getUser_uid()))
                        beRevokesOperatorNick= "你的";
                    else
                        beRevokesOperatorNick = " \"" + beNickname + "\" 的";
                }
                else
                    beRevokesOperatorNick = "";
            }
            else {
                beRevokesOperatorNick = "";
            }

            // 注意：同一条撤回提示，在不同的人看到时，显示的结果是不一样的：
            // (通过上述逻辑之后，组合成的结果有以下5种可能)
            //   1）" 你撤回了一条消息 "            （单聊或群聊时）
            //   2）" "李四"撤回了一条消息 "        （单聊或群聊时）
            //   3）" 你撤回了"张三"的一条消息 "     （群聊时）
            //   4）" "李四"撤回了你的一条消息 "     （群聊时）
            //   5）" "李四"撤回了"张三"的一条消息 " （群聊时）
            ret = MessageFormat.format(context.getString(R.string.chat_message_revoked_by_other_for_someone), revokedOperatorNick, beRevokesOperatorNick);

//            // 操作者是本地用户，就显示"你撤回了一条消息"
//            if(localRee != null && uidForOperator != null && uidForOperator.equals(localRee.getUser_uid())){
//                ret = context.getString(R.string.chat_message_revoked_by_yourself);
//            }
//            else{
//                ret = MessageFormat.format(context.getString(R.string.chat_message_revoked_by_other), CommonUtils.isStringEmpty(nickeNameForOperator)?"":nickeNameForOperator);
//            }
        }

        return ret;
    }

    public static Message prepareChatMessageData_incoming(String senderId, String senderDisplayName
            , String msg, Context context, long time, int msgType)
    {
        switch(msgType)
        {
            case MsgBody4Friend.TYPE_IMAGE:
                return createChatMsgEntity_INCOME_IMAGE(senderId, senderDisplayName, msg, time);
            case MsgBody4Friend.TYPE_VOICE:
                return createChatMsgEntity_INCOME_VOICE(senderId, senderDisplayName, msg, time);
            case MsgBody4Friend.TYPE_FILE: {
                // 文件消息的内容体是FileMeta对象的JSON形式
                FileMeta fm = FileMeta.fromJSON(msg);
                return createChatMsgEntity_INCOME_FILE(senderId, senderDisplayName, fm, time);
            }
            case MsgBody4Friend.TYPE_GIFT$SEND:
                return createChatMsgEntity_INCOME_GIFT$FOR$SEND(senderId, senderDisplayName, msg, time);
            case MsgBody4Friend.TYPE_GIFT$GET:
                return createChatMsgEntity_INCOME_GIFT$FOR$GET(senderId, senderDisplayName, msg, time);
            case MsgBody4Friend.TYPE_SYSTEAM$INFO:
                return createChatMsgEntity_INCOME_SYSTEAMINFO(senderId, msg, time);
            case MsgBody4Friend.TYPE_SHORTVIDEO: {
                // 短视频消息的内容体是FileMeta对象的JSON形式
                FileMeta fm = FileMeta.fromJSON(msg);
                return createChatMsgEntity_INCOME_SHORTVIDEO(senderId, senderDisplayName, fm, time);
            }
            case MsgBody4Friend.TYPE_CONTACT: {
                // 名片消息的内容体是ContactMeta对象的JSON形式
                ContactMeta cm = ContactMeta.fromJSON(msg);
                return createChatMsgEntity_INCOME_CONTACT(senderId, senderDisplayName, cm, time);
            }
            case MsgBody4Friend.TYPE_LOCATION: {
                // 位置消息的内容体是LocationMeta对象的JSON形式
                LocationMeta lm = LocationMeta.fromJSON(msg);
                return createChatMsgEntity_INCOME_LOCATION(senderId, senderDisplayName, lm, time);
            }
            case MsgBody4Friend.TYPE_REVOKE:
                return createChatMsgEntity_INCOME_REVOKE(senderId, msg, time);
            case MsgBody4Friend.TYPE_VOIP$RECORD: {
                // 位置消息的内容体是VoipRecordMeta对象的JSON形式
                VoipRecordMeta vrm = VoipRecordMeta.fromJSON(msg);
                return createChatMsgEntity_INCOME_VOIPRECORD(senderId, senderDisplayName, vrm, time);
            }
            default:
                return createChatMsgEntity_INCOME_TEXT(senderId, senderDisplayName, msg, time);
        }
    }
    //------------------------------------------------------------------------------------------- “收到”的消息的一些实用方法 END
}
